/*
 * @brief:
 * @Author: TzzzT
 * @Date: 2022-04-05 15:37:19
 * @LastEditTime: 2023-04-09 16:50:14
 * @LastEditors: TzzzT
 */
#pragma once

#include "stdint.h"
#include <stdio.h>
#include <time.h>
#include <sys/time.h>

#include "RCS_protocol.h"

/////////////////SYSTEM/////////////////
/*
区分设备，用户，游戏内玩家

设备：
    控制板
    接收板
    发射板
    设备可以和玩家断开，连接新的玩家。

用户：
    是游戏未开始时一个人在这个系统里的身份。主要负责通过蓝牙和手机通信，再和网络服务器通信。和服务器同步状态等信息。

角色：
    游戏开始以后的身份，不同的角色可以有不同技能属性等。

*/

//////////common//////////

// 事件
typedef enum rcs_event_class_e
{
    NO_EVENT = 0,
    CONNECT_SUCCESS,
    REMOTE_COMM_EVENT,
    BE_HITTED,
    HIT_SUCCESS,
} rcs_event_class_t;

typedef struct rcs_event_s
{
    rcs_event_class_t class;
    uint8_t count;
} rcs_event_t;

#define CONNECT_SUCCESS_EVENT_BIT 1 << CONNECT_SUCCESS
#define REMOTE_COMM_EVENT_BIT 1 << REMOTE_COMM_EVENT
#define BE_HITTED_EVENT_BIT 1 << BE_HITTED
#define HIT_SUCCESS_EVENT_BIT 1 << HIT_SUCCESS

#define BLE_CONNECT_DEV_NUM_MAX 8 //

#define BLUETOOTH_DEVICE_ADDR_LEN 6
typedef uint8_t bd_addr_t[BLUETOOTH_DEVICE_ADDR_LEN];

enum equip_class_e
{
    GUN_POINT_CLASS,
    GUN_SCREEN_CLASS,
    ARMOR_CLASS,
};

typedef struct gun_point_s
{
    bd_addr_t ser_bda;
    int8_t batt;
    uint8_t sn; // sn用来区分枪口和枪屏幕是否是同一组
    bool is_hold;
} gun_point_t;

typedef struct gun_screen_s
{
    bd_addr_t ser_bda;
    int8_t batt;
    uint8_t sn;
    bool is_hold;
} gun_screen_t;

typedef struct gun_device_s
{
    gun_point_t point;
    bool is_need_scr;
    gun_screen_t screen;
} gun_device_t;

typedef struct armor_s
{
    bd_addr_t ser_bda;
    int8_t batt;
    uint8_t sn;
    bool is_hold;
} armor_device_t;

typedef struct core_device_s
{
    bd_addr_t cli_bda;
    int8_t battery;
} core_device_t;

typedef struct equipment_s
{
    gun_device_t pri_weapon;
    // slave_member_t sec_weapon;
    armor_device_t armor;
    core_device_t core;
    uint8_t conn_num;
    bool low_batt_alert; // 全部设备的低电量警告
} equipment_t;

#define LOW_BATTERY 30
// 网卡

typedef uint8_t mac_t[8];

typedef struct net_dev_s
{
    mac_t mac_addr;
    bool is_live; // 有没有网卡
} net_dev_t;

#define LOW_BATTERY_THRESHOLD 30

typedef uint32_t player_id_t;
typedef int16_t bullet_num_t;
typedef int16_t player_hp_t;
typedef uint8_t player_kill_t;
typedef uint8_t player_death_t;
typedef int16_t player_damage_t;
typedef int16_t player_team_score_t;

typedef struct player_s
{
    uint16_t team_id;
    uint16_t room_id;
    uint8_t team;
    uint8_t room;
    player_damage_t damage;
    player_hp_t hp;
    player_id_t id; // 目前用设备的id等于用户的id，也等于玩家的id
    uint8_t kill;
    uint8_t death;
    int16_t team_score;
    bullet_num_t bullet_nums;
    bool living; // 游戏中状态
    bool is_in_invicible;
    bool is_in_fix_bullet_mode;
    bool is_in_continue_bullet_mode;
    int32_t death_player[5]; // 击杀自己的玩家
} player_t;

typedef struct game_s
{
    bool start;
    uint32_t record_id; // 游戏记录id,每一局游戏这个id不一样
    player_t player;
    bool have_net_in_start; // 游戏开始时是否有联网
} game_t;

typedef struct net_s
{
    net_dev_t dev;
    uint64_t request_id;
    bool is_connected;  // 是否连上网
    bool first_connect; //
    bool start_heartbeat;
} net_t;

// 目前用户就是负责和网络服务器对接信息，分别是连接手机蓝牙或者直接4g网络模块直接联网
typedef struct user_s
{
    uint32_t id;
} user_t;

// 与人绑定，有user结构体
typedef struct rcs_mast_system_s
{
    mac_t chip_mac;
    equipment_t equip;
    // uint64_t sys_time_ms;
    net_t net;
    user_t user;
    game_t game;
    rcs_event_t event; // 应该没用上
} rcs_mast_system_t;

typedef struct be_hitted_param_s
{
    player_id_t enemy_id;
    player_damage_t damage;
} be_hitted_param_t;

typedef struct startgame_param_s
{
    uint8_t start_flag;
} startgame_param_t;

typedef struct unknown_cmd_param_s
{
    error_net_source_t class;
    uint32_t data;
} unknown_cmd_param_t;

void take_mutex(void);
void give_mutex(void);

// void system_time_init(void)
// void update_system_time(uint64_t time_ms);
// void get_system_time(void);

void remember_sys_state(void);

void game_event_init(void);
void set_game_event(rcs_event_class_t _class, uint8_t _count);
void update_game_event(void);
rcs_event_t *get_game_event_state(void);

bool update_low_battery_alert_flag(void);

void get_user_id(void);

/////////////////GAME/////////////////
bool change_player_hp(player_hp_t new_hp);
bool change_player_damage(player_hp_t new_damage);
bool change_player_bullet_nums(bullet_num_t new_bullet_num);
bool change_player_team(uint8_t new);
bool change_player_room(uint8_t new);
bool change_player_team_score(player_team_score_t team_score);
bool change_player_death(player_death_t death);
bool change_player_kill(player_kill_t kill);
bool change_game_state(bool new_state);
bool reset_player(void);

esp_err_t store_ifnet_to_nvs(void);
esp_err_t get_ifnet_from_nvs(void);
esp_err_t store_game_start_to_nvs(void);
esp_err_t get_game_start_from_nvs(void);

void game_setting_init(void);

void make_prop_command_package(uint8_t *package, uint8_t package_len, uint8_t command, uint8_t batt);

uint8_t *make_hint_data_package(uint16_t *packlen, char *hint_data);
uint8_t *make_play_music_package(uint16_t *packlen, uint8_t music_sn);
uint8_t *make_sync_data_package(uint16_t *packlen, notify_mask_t mask);

void game_package_handle(uint8_t *buf);

/////////////////DEBUG/////////////////
#define DEBUG 1
uint8_t *event_name(rcs_event_t event);

//////////////////shock//////////////////

#define SHOCK_OUTPUT_PIN 5

void shock_init(void);
void set_shock(bool state);

//////////////////////////POWER//////////////////////////
#define POWER_PIN 10
void power_init(void);
void power_off(void);
/// 在rtos以外调用。
void delay_ms(uint16_t ms);

//////////////////////////BATTERY//////////////////////////
#define CALI 1
void battery_init(void);
uint8_t get_battery_percent(void);
